import time
from dashopt import settings
from django.http import JsonResponse, HttpResponseRedirect
from utils.baseview import BaseView
from django.core.cache import caches
from user.models import UserProfile, Address
from goods.models import SKU, SPUSaleAttr
from carts.views import CartsView
from django.db import transaction
from .models import OrderInfo, OrderGoods
from utils.myalipay import MyAlipay

CART_CACHE = caches['carts']


# Create your views here.
class AdvanceView(BaseView):
    def get(self, request, username):
        """
            确认订单页视图逻辑
        """
        # 1.第一个列表：address[{}, {}]
        user = request.myuser
        user_id = user.id
        addresses = self.get_address(user_id)
        # 2.第二个列表：sku_list[{}, {}]
        # http://127.0.0.1:8000/v1/orders/jiejie/advance?settlement_type=0
        # http://127.0.0.1:7000/dadashop/templates/orderConfirm.html?sku_id=2&buy_num=1
        # 区分链条 购物车:0, 立即购买-1
        typ = request.GET.get("settlement_type")
        cart_data = []
        if typ == "0":
            cart_data = self.get_carts(user_id)
        elif typ == "1":
            cart_data = self.get_skupay(user_id, request)
        result = {
            "code": 200,
            "data": {
                "addresses": addresses,
                "sku_list": cart_data
            },
            "base_url": settings.PIC_URL
        }
        return JsonResponse(result)

    def get_address(self, user_id):
        """
            获取某个用户所有的地址address
        """
        all_address = Address.objects.filter(user_profile_id=user_id, is_active=True).order_by("-is_default")
        addresses = []
        for add in all_address:
            add_dict = {
                "id": add.id,
                "name": add.receiver,
                "mobile": add.receiver_mobile,
                "title": add.tag,
                "address": add.address
            }
            addresses.append(add_dict)
        return addresses

    def get_carts(self, user_id):
        cart_data = CartsView().get_carts_list(user_id)
        cart_order = []
        for item in cart_data:
            if item.get("select"):
                cart_order.append(item)
        return cart_order

    def get_skupay(self, user_id, request):
        count = request.GET.get("buy_num")
        sku_id = request.GET.get("sku_id")
        sku_list = {}
        try:
            sku_data = SKU.objects.get(id=sku_id, is_launched=True)
        except Exception as e:
            return JsonResponse({"code": 30120, "error": "该商品已下架"})
        sku_list['name'] = sku_data.name
        sku_list['count'] = count
        sku_list['select'] = 1
        sku_list['default_image_url'] = str(sku_data.default_image_url)
        sku_list['price'] = sku_data.price
        # 销售属性值的id列表和name列表
        attr_value_query = sku_data.sale_attr_value.all()
        sku_list['sku_sale_attr_val'] = [i.name for i in attr_value_query]
        # 销售属性名的id列表和name列表
        attr_name_query = SPUSaleAttr.objects.filter(spu=sku_data.spu)
        sku_list['sku_sale_attr_name'] = [i.name for i in attr_name_query]
        return [sku_list]


class OrderInfoView(MyAlipay):
    def post(self, request, username):
        """
                两个地址：
                    1.购物车 - 去结算 - 确认付款 - 生成订单
                    需要删除购物车中已经转化为订单的商品数据
                    2.详情页 - 立即购买 - 确认付款 - 生成订单
                生成订单：{"code":200,  "data":{}, "base_url": "xxx"}
                data:
                    {
                        "addresses": [{},{},...],
                        "sku_list": [{},{},...]
                    }
                    {
                "addresses":
                    [ 
                    {
                        "id":1,
                        "name":"guoxiao",
                        "mobile":"13488873110",
                        "title":"家",
                        "address":"北京市北京市市辖区东城区啊啊啊"
                    }
                    ],
                "sku_list":
                    [
                    {
                        "id":2,
                        "name":"安踏A红色大尺寸",
                        "count":1,
                        "selected":1,
                        "default_image_url":"2_i2NMNkA.png",
                        "price":"200.00",
                        "sku_sale_attr_name":["安踏A/尺寸","安踏A/颜色"],
                        "sku_sale_attr_val":["18寸","红色"]
                    }
                    ]
                }
            """
        # 订单表插入数据， 订单商品表插入数据 , 更新sku的库存和销量, 删除购物车中已经转化为订单的商品数据
        data = request.data
        address_id = data.get("address_id")
        user = request.myuser
        if not user:
            return JsonResponse({"code": 302100, "error": "未查询到用户"})
        order_id = time.strftime("%Y%m%d%H%M%S") + str(user.id)  # 时间加用户id
        total_amount = 0
        total_count = 0
        # 地址
        try:
            add = Address.objects.get(id=address_id, user_profile=user, is_active=True)
        except Exception as e:
            return JsonResponse({"code": 302100, "error": "未查询到地址"})
        # 开启事务
        with transaction.atomic():
            sid = transaction.savepoint()
            # 订单表插入数据
            order = OrderInfo.objects.create(
                user_profile=user,
                order_id=order_id,
                total_amount=total_amount,
                total_count=total_count,
                pay_method=1,
                freight=1,
                status=1,
                receiver=add.receiver,
                address=add.address,
                receiver_mobile=add.receiver_mobile,
                tag=add.tag
            )
            # 更新sku库存和数量
            # {"1": [5, 1]}
            carts_dict = CartsView().get_carts_dict(user.id)
            skus = SKU.objects.filter(id__in=carts_dict.keys())
            for sku in skus:
                # 插入订单商品表
                count = carts_dict[str(sku.id)][0]
                while True:
                    if count > sku.stock:
                        transaction.savepoint_rollback(sid)
                        return JsonResponse({"code": 30421, "error": f"{sku.name}库存量不足，仅剩{sku.stock}"})
                    old_version = sku.version
                    result = SKU.objects.filter(id=sku.id, version=old_version).update(
                        stock=sku.stock - count,
                        sales=sku.sales + count,
                        version=old_version + 1
                    )
                    if not result:
                        # 操作未完成，回滚
                        continue
                    break
                # 订单商品表插入数据
                try:
                    OrderGoods.objects.create(
                        order_info_id=order_id,
                        sku_id=sku.id,
                        price=sku.price,
                        count=count
                    )
                except Exception as e:
                    print("訂單商品表數據插入失敗")
                    transaction.savepoint_rollback(sid)
                total_amount += sku.price * count
                total_count += count
                order.total_count = total_count
                order.total_amount = total_amount
                order.save()
            transaction.savepoint_commit(sid)
        # 清除购物车中有效商品数据
        carts_count = CartsView().delete_carts_dict(user.id)
        pay_url = self.get_pay_url(order_id, total_amount)
        result = {
            "code": 200,
            "data":
                {
                    'saller': '达达商城',
                    'total_amount': total_amount,
                    'order_id': order_id,
                    'pay_url': pay_url,
                    "carts_count": carts_count
                }
        }
        return JsonResponse(result)

    def get(self, request, username):
        type_order = int(request.GET.get('type'))
        order_id = request.GET.get('order_id')
        user = request.myuser
        if order_id and type == 5:
            order_pay_dict = self.get_order_pay(order_id)
            total_amount = order_pay_dict['total_amount']
            pay_url = order_pay_dict['pay_url']
            carts_count = CartsView().get_carts_dicts(user.id)
            result = {
                "code": 200,
                "data":
                    {
                        'saller': '达达商城',
                        'total_amount': total_amount,
                        'order_id': order_id,
                        'pay_url': pay_url,
                        "carts_count": carts_count
                    }
            }
            return JsonResponse(result)
        order_list = []
        if type_order in [0, 1, 2, 3, 4]:
            order_list = self.get_order(user, type_order)
        else:
            return JsonResponse({"code": 30102, "error_msg": "请选择合适的订单状态"})
        result = {
            "code": 200,
            "data": {
                "orders_list": order_list
            },
            "base_url": settings.PIC_URL
        }
        return JsonResponse(result)

    def get_order(self, user, type):
        orders = OrderInfo.objects.filter(user_profile_id=user.id,
                                          status=type) if type > 0 else OrderInfo.objects.filter(
            user_profile_id=user.id)
        order_list = []
        for item in orders:
            order = {}
            order['order_id'] = item.order_id
            order['order_total_count'] = item.total_count
            order['order_total_amount'] = item.total_amount
            order['order_freight'] = item.freight
            order['address'] = {
                "title": item.tag,
                "address": item.address,
                "mobile": item.receiver_mobile,
                "receiver": item.receiver
            }
            order['status'] = item.status
            order_goods = OrderGoods.objects.filter(order_info_id=item.order_id)
            sku_lists = []
            for sku in order_goods:
                sku_list = {}
                sku_data = sku.sku
                sku_list['id'] = sku_data.id
                sku_list['name'] = sku_data.name
                sku_list['count'] = sku.count
                sku_list['default_image_url'] = str(sku_data.default_image_url)
                sku_list['price'] = sku_data.price
                sku_list['total_amount'] = sku_data.price * sku.count
                # 销售属性值的id列表和name列表
                attr_value_query = sku_data.sale_attr_value.all()
                sku_list['sku_sale_attr_vals'] = [i.name for i in attr_value_query]
                # 销售属性名的id列表和name列表
                attr_name_query = SPUSaleAttr.objects.filter(spu=sku_data.spu)
                sku_list['sku_sale_attr_names'] = [i.name for i in attr_name_query]
                sku_lists.append(sku_list)
            order['order_sku'] = sku_lists
            order['order_time'] = item.created_time
            order_list.append(order)
        return order_list

    def get_pay_url(self, order_id, total_amount):
        params = self.alipay.api_alipay_trade_page_pay(
            subject=order_id,
            out_trade_no=order_id,
            total_amount=str(total_amount),
            # 同步通知地址[get]
            return_url=settings.ALIPAY_RETURN_URL,
            # 异步同志地址-公网IP
            notify_url=settings.ALIPAY_NOTIFY_URL,
        )
        pay_url = 'https://openapi-sandbox.dl.alipaydev.com/gateway.do?' + params
        return pay_url

    def get_order_pay(self, order_id):
        try:
            order = OrderInfo.objects.get(order_id=order_id)
        except Exception as e:
            print("error order -->", e)
            return JsonResponse({"code": 301200, "error_msg": e})
        pay_url = self.get_pay_url(order_id, order.total_amount)
        return {"pay_url": pay_url, 'total_amount': order.total_amount}


class ResultView(MyAlipay):
    def get(self, request):
        """
            同步通知【get】
            主动查询视图逻辑
            1.调用主动查询接口，获取支付结果
        """
        out_trade_no = request.GET.get("out_trade_no")
        trade_no = request.GET.get("trade_no")
        resp = self.alipay.api_alipay_trade_query(
            out_trade_no=out_trade_no,
            trade_no=trade_no
        )
        try:
            order = OrderInfo.objects.get(out_trade_no)
        except Exception as e:
            return JsonResponse("eroor")
        # 获取支付结果
        result = resp.get("trade_status")
        if result == "TRADE_SUCCESS":
            # 支付成功
            order.status = 2
        return HttpResponseRedirect("http://127.0.0.1:7000/dadashop/templates/index.html")

    def post(self, request):

        """
            notifyurl视图逻辑【异步通知】
            获取支付结果，修改订单状态
            1.获取请求体数据[接口文档]
            2.验证签名[使用Alipay公钥验证]
            3.修改订单状态组织返回
        """
        request_data = request.POST
        # QueryDict ----> Dict
        request_data = {k: request_data[k] for k in request_data.keys()}
        # 验签,结果为True or False
        sign = request_data.pop("sign")
        verify = self.alipay.verify(data=request_data, sign=sign)
        # 签名通过
        if verify:
            status = request_data.get("trade_status")
            if status == 'TRADE_SUCCESS':
                pass
        else:
            pass
